#include "gpio.h"
#include "time.h"
#include "ftuart.h"
#include "udelay.h"
#include "util.h"
#include "sean_i2c.h"
#include "bulverde.h"
#include "commandlist.h"
//#include "tat_menu.h"
#include "gsm.h"

#define RECVBUFLEN	1024

//#define LOOPBACK_FILTER 	1

char recv_buf[RECVBUFLEN];
int  change_flag = 1;


void ftuart_gpio_init()
{
        xs_setgpio_AFR(34, GPIO_AS_AF1);
        xs_setgpio_dir(34, GPIO_PIN_IN);

        xs_setgpio_AFR(37, GPIO_AS_AF3);
        xs_setgpio_dir(37, GPIO_PIN_OUT);

        xs_setgpio_AFR(26, GPIO_AS_AF3);
        xs_setgpio_dir(26, GPIO_PIN_IN);

        xs_setgpio_AFR(27, GPIO_AS_AF3);
        xs_setgpio_dir(27, GPIO_PIN_OUT);

        xs_setgpio_AFR(39, GPIO_AS_GPIO);
        xs_setgpio_dir(39, GPIO_PIN_OUT);

}

void ftuart_gpio_dein()
{
	xs_setgpio_AFR(34, GPIO_AS_AF1);
	xs_setgpio_dir(34, GPIO_PIN_IN);

	xs_setgpio_AFR(37, GPIO_AS_AF3);
	xs_setgpio_dir(37, GPIO_PIN_IN);

	xs_setgpio_AFR(26, GPIO_AS_AF3);
	xs_setgpio_dir(26, GPIO_PIN_IN);

	xs_setgpio_AFR(27, GPIO_AS_AF3);
	xs_setgpio_dir(27, GPIO_PIN_IN);

	xs_setgpio_AFR(39, GPIO_AS_GPIO);
	xs_setgpio_dir(39, GPIO_PIN_IN);
}



void bcm2121_gpio_init()
{
	//B_MODEM_WAKEUP
	xs_setgpio_AFR(114, GPIO_AS_GPIO);
	xs_setgpio_dir(114, GPIO_PIN_OUT);
	xs_setgpio_outhigh(114);

	//B_BB_HOST_WAKEUP
	xs_setgpio_AFR(38, GPIO_AS_GPIO);
	xs_setgpio_dir(38, GPIO_PIN_IN);

	//BT_32
	xs_setgpio_AFR(10, GPIO_AS_GPIO);
	xs_setgpio_dir(10, GPIO_PIN_IN);

	//BT_EJACK_RECO
	xs_setgpio_AFR(91, GPIO_AS_GPIO);
	xs_setgpio_dir(91, GPIO_PIN_IN);

	//B_BB_FLASH
	xs_setgpio_AFR(22, GPIO_AS_GPIO);
	xs_setgpio_dir(22, GPIO_PIN_OUT);

	//B_BB_RESETN
	xs_setgpio_AFR(23, GPIO_AS_GPIO);
	xs_setgpio_dir(23, GPIO_PIN_OUT);

	//B_ONKEY_N
	xs_setgpio_AFR(25, GPIO_AS_GPIO);
	xs_setgpio_dir(25, GPIO_PIN_OUT);

}


void bcm2121_on()
{

	xs_setgpio_outlow(23);

	//power on broadcom module
	xs_setgpio_outhigh(25);

	udelay(100);

	xs_setgpio_outhigh(23);

	return;
}

void bcm2121_Reset()
{
	xs_setgpio_outlow(23);
	udelay(100);
	xs_setgpio_outhigh(23);
}
void bcm2121_off()
{
	xs_setgpio_outlow(25);

	return;
}

void bcm2121_download_enable()
{
	xs_setgpio_outhigh(22);
}


void bcm2121_download_disable()
{
	xs_setgpio_outlow(22);
}

#if 0
void bcm2121_s2pc(struct command_data_struct *cmd)
{
	unsigned char data[2];

	ftuart_gpio_dein();

	bcm2121_download_enable();
	bcm2121_on();
	//modify the respond data
	cmd->Command = switch_onoff_GSM;
	cmd->Para = 0;		//command parameters :0x00 0x00  means:switch to PC
	data[0] = 0;
	data[1] = 0;
	cmd->Data_Ptr = data;	//command data :0x00 0x00 means:scuccessful
	cmd->Data_Len = 0x02;	//command length:0x0a

	change_flag = 0;	//clear the change_sw_flag,
				//let the UI know that modem has switched to pc

	do_response(*cmd);	//send response message to pc
	udelay(100);
	return;
}


void bcm2121_s2bvd(struct command_data_struct *cmd)
{
	unsigned data[2];

	bcm2121_download_disable();

	gsm_ffuart_init();

	//adjust baudrate of modem to syn with bulverde btuart
	ftuart_output_byte('AT+CFUN=1 \r');
	ftuart_output_byte('\r');

	printk("adjust ok!\r\n");

	//modify the respond data
	cmd->Command = switch_onoff_GSM;
	cmd->Para = 0x01;		//command parameters :0x00 0x01.means:switch to bvd
	data[0] = 0;
	data[1] = 0;
	cmd->Data_Ptr = data;	//command data :0x00 0x00. means:scuccessful
	cmd->Data_Len = 0x02;	//command length:0x0a


	do_response(*cmd);//send response message to pc
	change_flag = 1;	//set the change_sw_flag,
				//let the UI know that modem has switched to bulverde

	return;
}

void bcm2121_Reset_2bvd(struct command_data_struct *cmd)
{
	unsigned char data[2];
	bcm2121_Reset();

	cmd->Command = switch_onoff_GSM;
	cmd->Para = 0x03;		//command parameters :0x00 0x01.means:switch to bvd
	data[0] = 0;
	data[1] = 0;
	cmd->Data_Ptr = data;	//command data :0x00 0x00. means:scuccessful
	cmd->Data_Len = 0x02;	//command length:0x0a

	do_response(*cmd);//send response message to pc
	change_flag = 1;	//set the change_sw_flag

	return;
}
void bcm2121_off_2bvd(struct command_data_struct *cmd)
{
	unsigned char data[2];
	bcm2121_off();

	ftuart_gpio_init();

	cmd->Command = switch_onoff_GSM;
	cmd->Para = 0x02;		//command parameters :0x00 0x01.means:switch to bvd
	data[0] = 0;
	data[1] = 0;
	cmd->Data_Ptr = data;	//command data :0x00 0x00. means:scuccessful
	cmd->Data_Len = 0x02;	//command length:0x0a

	do_response(*cmd);//send response message to pc
	change_flag = 1;	//set the change_sw_flag

	return;
}

int swt_onoff_gsm( struct command_data_struct command_data )
{
	unsigned short para;
	unsigned char data[2];


	bcm2121_gpio_init();

	para = command_data.Para;
	if ( para != 0 && para != 0x01 && para != 0x02 && para !=0x03)	//if para err,send failed message to pc
	{
		//wls_printf("Error: %s\n", get_error_string() );

		command_data.Command = switch_onoff_GSM;
		//command_data.Para = 0x01;
		data[0] = 0;
		data[1] = 1;
		command_data.Data_Ptr = data;	//command data :0x00 0x01. means:failture
		command_data.Data_Len = 0x02;	//command length:0x0a
		do_response(command_data);	//send failture message to pc
		return FALSE;
	}
	if ( para == 0 )		//switch to PC
	{
		bcm2121_s2pc(&command_data);
	}
	if ( para == 0x01 )		//switch to bulverde
	{
		bcm2121_s2bvd(&command_data);
	}
	if ( para == 0x02 )
	{
		bcm2121_off_2bvd(&command_data);
	}
	if( para == 0x03 )
	{
	     bcm2121_Reset_2bvd(&command_data);
	}
	return TRUE;
}


int change_sw_flag( struct command_data_struct command_data )
{
	command_data.Para = ( unsigned short )change_flag;	//send change_flage to PC to tell that cms92
								//switch to bulverde or to PC.
	do_response( command_data );
	return TRUE;
}


#ifdef LOOPBACK_FILTER
int atcmd_loopback_filter( struct command_data_struct *cmd )
{
	int i;
	int count;
	int head,trail;
	int loopback_len;
	char flag;

	i = 0;
	count = 0;
	head = 0;
	trail = 0;
	//filter loopback data from cms92
	for ( i = 0;i < cmd->Data_Len;i++ )
	{
		switch( count )
		{
		 case 0:if( cmd->Data_Ptr[i] == 0x0d ) count = 1;
			if( cmd->Data_Ptr[i] == 0x41 || cmd->Data_Ptr[i] == 0x61 )
			{
				count = 8;
				flag = 1;
			}
			break;
		 case 1:if( cmd->Data_Ptr[i] == 0x0a ) count = 2;
			else count = 0;
			break;
		 case 2:if( cmd->Data_Ptr[i] == 0x41 || cmd->Data_Ptr[i] == 0x61 ) count = 3;
			else count = 0;
			break;
		 case 3:if( cmd->Data_Ptr[i] == 0x54 || cmd->Data_Ptr[i] == 0x74 )
			{
				count = 4;
				head = i-3;
			}
			else count = 0;
			break;
		 case 4:if( cmd->Data_Ptr[i] == 0x0d ) count = 5;
			else count = 4;
			break;
		 case 5:if( cmd->Data_Ptr[i] == 0x0a )
			{
				count = 6;
				trail = i;
			}
			else
			{
				 count = 7;
				 trail = i-1;
			}
			break;
		 case 8:if( cmd->Data_Ptr[i] == 0x54 || cmd->Data_Ptr[i] == 0x74 )
			{
				count = 4;
				head = i-1;
			}
			else count = 0;
			break;
		 default:break;
		}
		if ( count == 6 || count == 7 ) break;
	}

	if ( trail != 0 )
	{
		loopback_len = trail - head + 1;
		//for ( i = head;i<=trail;i++)
		//	cmd->Data_Ptr[i] = cmd->Data_Ptr[i + loopback_len];
		cmd->Data_Ptr = &cmd->Data_Ptr[head+loopback_len];

		cmd->Data_Len = cmd->Data_Len - loopback_len;
	}

	return TRUE;
}
#endif

void bvd_send_cmd(unsigned char *cmdstr,int strlen)
{
	int i;

	for(i = 0; i < strlen; i++)
	{
		ftuart_output_byte((const char)cmdstr[i]);
		printk("cmdstr:%04x *",cmdstr[i]);
	}
	ftuart_output_byte('\r');
	return;
}

void bvd_recv_cmd(struct command_data_struct  *cmd)
{
	unsigned char ch;
	int c;
	int i;

	//ftuart_clear_rx();

	for(i = 0; i < RECVBUFLEN; i++)
	{
		c = ftuart_input_byte((char *)&ch);

		if(c == 0)	break;
		cmd->Data_Ptr[i] = (unsigned char)ch;
	//	printk("input:%02x **",cmd->Data_Ptr[i]);
	}
	cmd->Data_Len = i;
	//printk("len:%04x **",cmd->Data_Len);

	return;
}

int gsm_ffuart_init()
{
	ftuart_gpio_init();
	bcm2121_gpio_init();

	bcm2121_download_disable();
	bcm2121_on();
	ftuart_init(baud115k2);
	udelay(100);

	return 1;
}

int send_atcmd_gsm( struct command_data_struct command_data )
{
	unsigned int i;
	struct command_data_struct *cmd;

	//gsm_ffuart_init();

	cmd = &command_data;
	bvd_send_cmd(cmd->Data_Ptr,cmd->Data_Len);	//send AT command to gsm
	bvd_recv_cmd(cmd);
#ifdef LOOPBACK_FILTER
	atcmd_loopback_filter(cmd);
#endif
	//printk("cmd2->Len:%04x ***",cmd->Data_Len);
	do_response(*cmd);
	return TRUE;
}
#endif
